home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / elm2.2 / part17 < prev    next >
Encoding:
Internet Message Format  |  1989-04-12  |  49.4 KB

  1. Subject:  v18i096:  Elm mail system, release 2.2, Part17/24
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
  7. Posting-number: Volume 18, Issue 96
  8. Archive-name: elm2.2/part17
  9.  
  10. #!/bin/sh
  11. # this is part 17 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file src/mailmsg2.c continued
  14. #
  15. CurArch=17
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file src/mailmsg2.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> src/mailmsg2.c
  27. X        that...
  28. X        Return TRUE if the main part of the screen has been changed
  29. X        (useful for knowing whether a redraw is needed.
  30. X    **/
  31. X
  32. X    FILE *reply, *real_reply; /* second is post-input buffer */
  33. X    char *whole_msg_file, *tempnam();
  34. X    char filename[SLEN], filename2[SLEN], fname[SLEN], copy_file[SLEN],
  35. X             very_long_buffer[VERY_LONG_STRING], mailerflags[NLEN];
  36. X    int ch;
  37. X    register int retransmit = FALSE; 
  38. X    int      already_has_text = FALSE;        /* we need an ADDRESS */
  39. X    int     need_redraw = 0;
  40. X
  41. X    static int cancelled_msg = 0;
  42. X
  43. X    dprint(4, (debugfile, "\nMailing to \"%s\" (with%s editing)\n",
  44. X          expanded_to, edit_message? "" : "out"));
  45. X    
  46. X    gotten_key = 0;        /* ignore previously gotten encryption key */
  47. X
  48. X    /** first generate the temporary filename **/
  49. X
  50. X    sprintf(filename,"%s%d",temp_file, getpid());
  51. X
  52. X    /** if possible, let's try to recall the last message? **/
  53. X
  54. X    if (! batch_only && copy_msg != FORM && user_level != 0)
  55. X      retransmit = recall_last_msg(filename, copy_msg, &cancelled_msg, 
  56. X               &already_has_text);
  57. X
  58. X    /** if we're not retransmitting, create the file.. **/
  59. X
  60. X    if (! retransmit)
  61. X      if ((reply = fopen(filename,"w")) == NULL) {
  62. X        dprint(1, (debugfile, 
  63. X               "Attempt to write to temp file %s failed with error %s (mail)\n",
  64. X         filename, error_name(errno)));
  65. X        if(batch_only)
  66. X          printf("Could not create file %s (%s).\n",filename,
  67. X         error_name(errno));
  68. X        else
  69. X          error2("Could not create file %s (%s).",filename,
  70. X         error_name(errno));
  71. X        return(need_redraw);
  72. X      }
  73. X
  74. X    chown (filename, userid, groupid);
  75. X
  76. X    /* copy the message from standard input */
  77. X    if (batch_only) {
  78. X      while (fgets(very_long_buffer, VERY_LONG_STRING, stdin) != NULL) 
  79. X        fprintf(reply, "%s", very_long_buffer);
  80. X    }
  81. X
  82. X    if (copy_msg == FORM) {
  83. X      sprintf(fname, "%s%d", temp_form_file, getpid());
  84. X      fclose(reply);    /* we can't retransmit a form! */
  85. X      if (access(fname,ACCESS_EXISTS) != 0) {
  86. X        if(batch_only)
  87. X          printf("Couldn't find forms file!\n");
  88. X        else
  89. X          error("Couldn't find forms file!");
  90. X        return(need_redraw);
  91. X      }
  92. X      dprint(4, (debugfile, "-- renaming existing file %s to file %s --\n",
  93. X          fname, filename));
  94. X      rename(fname, filename);
  95. X    }
  96. X    else if (copy_msg && ! retransmit)    /* if retransmit we have it! */
  97. X      if (edit_message) {
  98. X        copy_message(prefixchars, reply, noheader, FALSE, FALSE);
  99. X        already_has_text = TRUE;    /* we just added it, right? */
  100. X      }
  101. X      else
  102. X        copy_message("", reply, noheader, FALSE, FALSE);
  103. X
  104. X    if (!batch_only && !retransmit && copy_msg != FORM) {
  105. X      char *sig;
  106. X
  107. X      if (chloc(expanded_to, '!') == -1 && chloc(expanded_to, '@') == -1)
  108. X        sig = local_signature;
  109. X      else
  110. X        sig = remote_signature;
  111. X
  112. X      if (sig[0]) {
  113. X        fprintf(reply, "\n-- \n");  /* News 2.11 compatibility? */
  114. X        if (sig[0] != '/')
  115. X          sprintf(filename2, "%s/%s", home, sig);
  116. X        else
  117. X          strcpy(filename2, sig);
  118. X        (void) append(reply, filename2);
  119. X        already_has_text = TRUE;  /* added signature... */
  120. X      }
  121. X    }
  122. X
  123. X    if (! retransmit && copy_msg != FORM)
  124. X      if (reply != NULL)
  125. X        (void) fclose(reply);    /* on replies, it won't be open! */
  126. X
  127. X    /** Edit the message **/
  128. X
  129. X    if (edit_message)
  130. X      create_readmsg_file();    /* for "readmsg" routine */
  131. X
  132. X    ch = edit_message? 'e' : ' ';    /* drop through if needed... */
  133. X
  134. X    /* calculate default save_file name */
  135. X    if(auto_cc) {
  136. X      if(save_by_name)
  137. X        strcpy(copy_file, "=");    /* signals save by 'to' logname */
  138. X      else
  139. X        strcpy(copy_file, "<");    /* signals save to sentmail */
  140. X    } else *copy_file = '\0';    /* signals to not save a copy */
  141. X
  142. X
  143. X    if (! batch_only) {
  144. X      do {
  145. X        switch (ch) {
  146. X          case 'e': if (edit_the_message(filename, already_has_text)) {
  147. X              cancelled_msg = TRUE;
  148. X              return(need_redraw);
  149. X            }
  150. X            need_redraw++;
  151. X            break;
  152. X
  153. X          case 'c': need_redraw += name_copy_file(copy_file);
  154. X            break;
  155. X
  156. X          case 'h': edit_headers();
  157. X            need_redraw++;
  158. X            break;
  159. X
  160. X          default : /* do nothing */ ;
  161. X        }
  162. X
  163. X        /** ask that silly question again... **/
  164. X  
  165. X        if ((ch = verify_transmission(filename, &form)) == 'f') {
  166. X          cancelled_msg = TRUE;
  167. X          return(need_redraw);
  168. X        }
  169. X
  170. X      } while (ch != 's');
  171. X
  172. X      if (form == YES) 
  173. X        if (format_form(filename) < 1) {
  174. X          cancelled_msg = TRUE;
  175. X          return(need_redraw);
  176. X        }
  177. X
  178. X      if ((reply = fopen(filename,"r")) == NULL) {
  179. X          dprint(1, (debugfile,
  180. X        "Attempt to open file %s for reading failed with error %s (mail)\n",
  181. X                filename, error_name(errno)));
  182. X          error1("Could not open reply file (%s).", error_name(errno));
  183. X          return(need_redraw);
  184. X      }
  185. X    }
  186. X    else if ((reply = fopen(filename,"r")) == NULL) {
  187. X      dprint(1, (debugfile, 
  188. X        "Attempt to open file %s for reading failed with error %s (mail)\n",
  189. X             filename, error_name(errno)));
  190. X      printf("Could not open reply file (%s).\n", error_name(errno));
  191. X      return(need_redraw);
  192. X    }
  193. X
  194. X    cancelled_msg = FALSE;    /* it ain't cancelled, is it? */
  195. X
  196. X    /** ask about bounceback if the user wants us to.... **/
  197. X
  198. X    if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM) 
  199. X      if (verify_bounceback() == TRUE) {
  200. X        if (strlen(cc) > 0) strcat(expanded_cc, ", ");
  201. X        strcat(expanded_cc, bounce_off_remote(to));
  202. X      }
  203. X
  204. X    /** grab a copy if the user so desires... **/
  205. X
  206. X    if (*copy_file) /* i.e. if copy_file contains a name */
  207. X      save_copy(expanded_to, expanded_cc, expanded_bcc,
  208. X           filename, copy_file, form);
  209. X
  210. X    /** write all header information into whole_msg_file **/
  211. X
  212. X    if((whole_msg_file=tempnam(temp_dir, "snd.")) == NULL) {
  213. X      dprint(1, (debugfile, "couldn't make temp file nam! (mail)\n"));
  214. X      if(batch_only)
  215. X        printf("Sorry - couldn't make temp file name!\n");
  216. X      else if(mail_only)
  217. X        error("Sorry - couldn't make temp file name.");
  218. X      else
  219. X        set_error("Sorry - couldn't make temp file name.");
  220. X      return(need_redraw);
  221. X    }
  222. X
  223. X    /** try to write headers to new temp file **/
  224. X
  225. X    dprint(6, (debugfile, "Composition file='%s' and mail buffer='%s'\n", 
  226. X            filename, whole_msg_file));
  227. X
  228. X    dprint(2,(debugfile,"--\nTo: %s\nCc: %s\nBcc: %s\nSubject: %s\n---\n", 
  229. X          expanded_to, expanded_cc, expanded_bcc, subject));
  230. X
  231. X    if ((real_reply=
  232. X       write_header_info(whole_msg_file, expanded_to,
  233. X         expanded_cc, expanded_bcc, form == YES, FALSE)) == NULL) {
  234. X
  235. X      /** IT FAILED!!  MEIN GOTT!  Use a dumb mailer instead! **/
  236. X
  237. X      dprint(3, (debugfile, "** write_header failed: %s\n", 
  238. X         error_name(errno)));
  239. X
  240. X      if (cc[0] != '\0')          /* copies! */
  241. X        sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
  242. X
  243. X      sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
  244. X                  mailx, subject, strip_parens(strip_commas(expanded_to)), 
  245. X          remove_cmd, filename, filename);
  246. X
  247. X      if(batch_only)
  248. X        printf("Message sent using dumb mailer %s.\n", mailx);
  249. X      else
  250. X        error1("Message sent using dumb mailer %s.", mailx);
  251. X      sleep(2);    /* ensure time to see this prompt! */
  252. X
  253. X    }
  254. X    else {
  255. X      copy_message_across(reply, real_reply, FALSE);
  256. X
  257. X      fclose(real_reply);
  258. X
  259. X      if (cc[0] != '\0')                           /* copies! */
  260. X        sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
  261. X
  262. X      if (bcc[0] != '\0') {
  263. X        strcat(expanded_to, " ");
  264. X        strcat(expanded_to, expanded_bcc);
  265. X      }
  266. X
  267. X      if (strcmp(sendmail, mailer) == 0
  268. X#ifdef SITE_HIDING
  269. X          && ! is_a_hidden_user(username))
  270. X#else
  271. X                             )
  272. X#endif
  273. X        
  274. X         strcpy(mailerflags, (sendmail_verbose ? smflagsv : smflags));
  275. X      else
  276. X         mailerflags[0] ='\0';
  277. X
  278. X      sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s", 
  279. X        mailer, mailerflags, strip_parens(strip_commas(expanded_to)), 
  280. X        remove_cmd, whole_msg_file, whole_msg_file);
  281. X    }
  282. X    
  283. X    fclose(reply);
  284. X
  285. X    if(batch_only)
  286. X      printf("Sending mail...\n");
  287. X    else {
  288. X      PutLine0(LINES,0,"Sending mail...");
  289. X      CleartoEOLN();
  290. X    }
  291. X
  292. X    system_call(very_long_buffer, SH, FALSE);
  293. X
  294. X    /* Unlink temp file now.
  295. X     * This is a precaution in case the message was encrypted.
  296. X     * I.e. even though this file is readable by the owner only,
  297. X     * encryption is supposed to hide things even from someone
  298. X     * with root privelges. The best we can do is not let this
  299. X     * file just hang after we're finished with it.
  300. X     */
  301. X    (void)unlink(filename);
  302. X
  303. X    if(batch_only)
  304. X      printf("Mail sent!\n");
  305. X    else if(mail_only)
  306. X      error("Mail sent!");
  307. X    else
  308. X      set_error("Mail sent!");
  309. X
  310. X    return(need_redraw);
  311. X}
  312. X
  313. Xmail_form(address, subj)
  314. Xchar *address, *subj;
  315. X{
  316. X    /** copy the appropriate variables to the shared space... */
  317. X
  318. X    strcpy(subject, subj);
  319. X    strcpy(to, address);
  320. X    strcpy(expanded_to, address);
  321. X
  322. X    return(mail(FORM, NO, NO));
  323. X}
  324. X
  325. Xint
  326. Xrecall_last_msg(filename, copy_msg, cancelled_msg, already_has_text)
  327. Xchar *filename;
  328. Xint  copy_msg, *cancelled_msg, *already_has_text;
  329. X{
  330. X    char ch;
  331. X
  332. X    /** If filename exists and we've recently cancelled a message,
  333. X        the ask if the user wants to use that message instead!  This
  334. X        routine returns TRUE if the user wants to retransmit the last
  335. X        message, FALSE otherwise...
  336. X    **/
  337. X
  338. X    register int retransmit = FALSE;
  339. X
  340. X    if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
  341. X      Raw(ON);
  342. X      CleartoEOLN();
  343. X      if (copy_msg)
  344. X        PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
  345. X             BACKSPACE);
  346. X      else
  347. X        PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c", 
  348. X             BACKSPACE);
  349. X      fflush(stdout);
  350. X      ch = ReadCh();
  351. X      if (tolower(ch) != 'n') {
  352. X        Write_to_screen("Yes.",0);    
  353. X            retransmit++;
  354. X        *already_has_text = TRUE;
  355. X      }
  356. X      else 
  357. X        Write_to_screen("No.",0);    
  358. X
  359. X      fflush(stdout);
  360. X
  361. X      *cancelled_msg = 0;
  362. X    }
  363. X
  364. X    return(retransmit);
  365. X}
  366. X
  367. Xint
  368. Xverify_transmission(filename, form_letter)
  369. Xchar *filename;
  370. Xint  *form_letter;
  371. X{
  372. X    /** Ensure the user wants to send this.  This routine returns
  373. X        the character entered.  Modified compliments of Steve Wolf 
  374. X        to add the'dead.letter' feature.
  375. X        Also added form letter support... 
  376. X    **/
  377. X
  378. X    FILE *deadfd, *messagefd;
  379. X    char ch, buffer[SLEN], fname[SLEN];
  380. X    int x_coord, y_coord;
  381. X
  382. X    while(1) {
  383. X      /* clear bottom part of screen */
  384. X      MoveCursor(LINES-2,0);
  385. X      CleartoEOS();
  386. X
  387. X      /* display prompt and menu according to
  388. X       * user level and what's available on the menu */
  389. X      if (user_level == 0) {
  390. X        PutLine0(LINES-2,0,
  391. X      "Please choose one of the following options by parenthesized letter: s");
  392. X        GetXYLocation(&x_coord, &y_coord);
  393. X        y_coord--;    /* backspace over default answer */
  394. X        Centerline(LINES-1,
  395. X          "e)dit message, edit h)eaders, s)end it, or f)orget it.");
  396. X      } else {
  397. X        PutLine0(LINES-2, 0, "And now: s");
  398. X        GetXYLocation(&x_coord, &y_coord);
  399. X        y_coord--;    /* backspace over default answer */
  400. X        if (*form_letter == PREFORMATTED)  {
  401. X    Centerline(LINES-1, "Choose h)eaders, s)end, c)opy file, or f)orget.");
  402. X        } else if (*form_letter == YES) {
  403. X          Centerline(LINES-1,
  404. X        "Choose e)dit form, h)eaders, s)end, c)opy file, or f)orget.");
  405. X        } else if (*form_letter == MAYBE)  {
  406. X          Centerline(LINES-1,
  407. X  "Choose e)dit message, h)eaders, m)ake form, s)end, c)opy file, or f)orget.");
  408. X        } else {
  409. X          Centerline(LINES-1,
  410. X          "Choose e)dit message, h)eaders, s)end, c)opy file, or f)orget.");
  411. X        }
  412. X      }
  413. X
  414. X      /* wait for answer */
  415. X      fflush(stdin);
  416. X      fflush(stdout);
  417. X      Raw(ON);    /* double check... testing only... */
  418. X      MoveCursor(x_coord, y_coord);
  419. X      ch = ReadCh();
  420. X      ch = tolower(ch);
  421. X
  422. X      /* process answer */
  423. X      switch (ch) {
  424. X         case 'f': Write_to_screen("Forget",0);
  425. X               if (mail_only) {
  426. X             /** try to save it as a dead letter file **/
  427. X             save_file_stats(fname);
  428. X             sprintf(fname, "%s/%s", home, dead_letter);
  429. X             if ((deadfd = fopen(fname,"a")) == NULL) {
  430. X               dprint(1, (debugfile,
  431. X           "\nAttempt to append to deadletter file '%s' failed: %s\n\r",
  432. X                   fname, error_name(errno)));
  433. X               error("Message not saved, Sorry.");
  434. X             }
  435. X             else if ((messagefd = fopen(filename, "r")) == NULL) {
  436. X               dprint(1, (debugfile,
  437. X                 "\nAttempt to read reply file '%s' failed: %s\n\r",
  438. X                   filename, error_name(errno)));
  439. X               error("Message not saved, Sorry.");
  440. X             } else {
  441. X               /* if we get here we're okay for everything */
  442. X               while (fgets(buffer, SLEN, messagefd) != NULL)
  443. X                 fputs(buffer, deadfd);
  444. X
  445. X               fclose(messagefd);
  446. X               fclose(deadfd);
  447. X               restore_file_stats(fname);
  448. X
  449. X               error1("Message saved in file \"$HOME/%s\".",
  450. X                 dead_letter);
  451. X
  452. X            }
  453. X               } else set_error(
  454. X          "Message kept. Can be restored at next f)orward, m)ail or r)eply.");
  455. X               break;
  456. X
  457. X         case '\n' :
  458. X         case '\r' :
  459. X         case 's'  : Write_to_screen("Send",0);
  460. X             ch = 's';        /* make sure! */
  461. X             break;
  462. X
  463. X         case 'm'  : if (*form_letter == MAYBE) {
  464. X               *form_letter = YES;
  465. X                   switch (check_form_file(filename)) {
  466. X                 case -1 : return('f');
  467. X                 case 0  : *form_letter = MAYBE;  /* check later!*/
  468. X                       error("No fields in form!");
  469. X                       return('e');
  470. X                 default : continue;
  471. X                       }
  472. X             }
  473. X             else {
  474. X                        Write_to_screen("%c??", 1, 07);    /* BEEP */
  475. X                sleep(1);
  476. X                    continue;
  477. X                     }
  478. X         case 'e'  :  if (*form_letter != PREFORMATTED) {
  479. X                Write_to_screen("Edit",0);
  480. X                     if (*form_letter == YES) 
  481. X                  *form_letter = MAYBE;
  482. X                      }
  483. X              else {
  484. X                        Write_to_screen("%c??", 1, 07);    /* BEEP */
  485. X                sleep(1);
  486. X                    continue;
  487. X                     }
  488. X             break;
  489. X
  490. X         case 'h'  : Write_to_screen("Headers",0);
  491. X             break;
  492. X
  493. X         case 'c'  : Write_to_screen("Copy file",0);
  494. X             break;
  495. X
  496. X         default   : Write_to_screen("%c??", 1, 07);    /* BEEP */
  497. X             sleep(1);
  498. X                 continue;
  499. X       }
  500. X
  501. X       return(ch);
  502. X    }
  503. X}
  504. X
  505. XFILE *
  506. Xwrite_header_info(filename, long_to, long_cc, long_bcc, form, copy)
  507. Xchar *filename, *long_to, *long_cc, *long_bcc;
  508. Xint   form, copy;
  509. X{
  510. X    /** Try to open filedesc as the specified filename.  If we can,
  511. X        then write all the headers into the file.  The routine returns
  512. X        'filedesc' if it succeeded, NULL otherwise.  Added the ability
  513. X        to have backquoted stuff in the users .elmheaders file!
  514. X        If copy is TRUE, then treat this as the saved copy of outbound
  515. X        mail.
  516. X    **/
  517. X
  518. X    char opentype[2];
  519. X    long time(), thetime;
  520. X    char *ctime();
  521. X    static FILE *filedesc;        /* our friendly file descriptor  */
  522. X
  523. X#ifdef SITE_HIDING
  524. X    char  buffer[SLEN];
  525. X    int   is_hidden_user;        /* someone we should know about?  */
  526. X#endif
  527. X
  528. X    char  *get_arpa_date();
  529. X
  530. X    if(copy)
  531. X        strcpy(opentype, "a");
  532. X    else
  533. X        strcpy(opentype, "w");
  534. X
  535. X    save_file_stats(filename);
  536. X    if ((filedesc = fopen(filename, opentype)) == NULL) {
  537. X      dprint(1, (debugfile,
  538. X        "Attempt to open file %s for writing failed! (write_header_info)\n",
  539. X         filename));
  540. X      dprint(1, (debugfile, "** %s - %s **\n\n", error_name(errno),
  541. X         error_description(errno)));
  542. X      error2("Error %s encountered trying to write to %s.", 
  543. X        error_name(errno), filename);
  544. X      sleep(2);
  545. X      return(NULL);        /* couldn't open it!! */
  546. X    }
  547. X
  548. X    restore_file_stats(filename);
  549. X
  550. X    if(copy) {    /* Add top line that mailer would add */
  551. X      thetime = time((long *) 0);
  552. X      fprintf(filedesc,"From %s %s", username, ctime(&thetime));
  553. X    }
  554. X
  555. X#ifdef SITE_HIDING
  556. X    if ( !copy && (is_hidden_user = is_a_hidden_user(username))) {
  557. X      /** this is the interesting part of this trick... **/
  558. X      sprintf(buffer, "From %s!%s %s\n",  HIDDEN_SITE_NAME,
  559. X          username, get_ctime_date());
  560. X      fprintf(filedesc, "%s", buffer);
  561. X      dprint(1,(debugfile, "\nadded: %s", buffer));
  562. X      /** so is this perverted or what? **/
  563. X    }
  564. X#endif
  565. X
  566. X
  567. X    /** Subject moved to top of headers for mail because the
  568. X        pure System V.3 mailer, in its infinite wisdom, now
  569. X        assumes that anything the user sends is part of the 
  570. X        message body unless either:
  571. X        1. the "-s" flag is used (although it doesn't seem
  572. X           to be supported on all implementations??)
  573. X        2. the first line is "Subject:".  If so, then it'll
  574. X           read until a blank line and assume all are meant
  575. X           to be headers.
  576. X        So the gory solution here is to move the Subject: line
  577. X        up to the top.  I assume it won't break anyone elses program
  578. X        or anything anyway (besides, RFC-822 specifies that the *order*
  579. X        of headers is irrelevant).  Gahhhhh....
  580. X    **/
  581. X
  582. X    fprintf(filedesc, "Subject: %s\n", subject);
  583. X
  584. X      fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
  585. X
  586. X    fprintf(filedesc,"Date: %s\n", get_arpa_date());
  587. X
  588. X#ifndef DONT_ADD_FROM
  589. X# ifdef SITE_HIDING
  590. X    if (is_hidden_user)
  591. X      fprintf(filedesc,"From: %s <%s!%s!%s>\n", full_username,
  592. X          hostname, HIDDEN_SITE_NAME, username);
  593. X    else
  594. X# else
  595. X#  ifdef  INTERNET
  596. X#   ifdef  USE_DOMAIN
  597. X    fprintf(filedesc,"From: %s <%s@%s%s>\n", full_username, 
  598. X        username, hostname, hostdomain);
  599. X#   else
  600. X    fprintf(filedesc,"From: %s <%s@%s>\n", full_username,
  601. X        username, hostname);
  602. X#   endif
  603. X#  else
  604. X    fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
  605. X        hostname, username);
  606. X#  endif
  607. X# endif
  608. X#endif
  609. X
  610. X    if (cc[0] != '\0')
  611. X        fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
  612. X
  613. X    if (copy && (bcc[0] != '\0'))
  614. X        fprintf(filedesc, "Bcc: %s\n", format_long(long_bcc, strlen("Bcc: ")));
  615. X
  616. X    if (strlen(action) > 0)
  617. X        fprintf(filedesc, "Action: %s\n", action);
  618. X    
  619. X    if (strlen(priority) > 0)
  620. X        fprintf(filedesc, "Priority: %s\n", priority);
  621. X    
  622. X    if (strlen(expires) > 0)
  623. X        fprintf(filedesc, "Expires: %s\n", expires);
  624. X    
  625. X    if (strlen(reply_to) > 0)
  626. X        fprintf(filedesc, "Reply-To: %s\n", reply_to);
  627. X
  628. X    if (strlen(in_reply_to) > 0)
  629. X        fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
  630. X
  631. X    if (strlen(user_defined_header) > 0)
  632. X        fprintf(filedesc, "%s\n", user_defined_header);
  633. X
  634. X    add_mailheaders(filedesc);
  635. X
  636. X    if (form)
  637. X      fprintf(filedesc, "Content-Type: mailform\n");
  638. X
  639. X    fprintf(filedesc, "X-Mailer: ELM [version %s]\n\n", version_buff);
  640. X
  641. X    return((FILE *) filedesc);
  642. X}
  643. X
  644. Xcopy_message_across(source, dest, copy)
  645. XFILE *source, *dest;
  646. Xint copy;
  647. X{
  648. X    /** Copy the message in the file pointed to by source to the
  649. X        file pointed to by dest.
  650. X        If copy is TRUE, treat as a saved copy of outbound mail. **/
  651. X
  652. X    int  crypted = FALSE;            /* are we encrypting?  */
  653. X    int  encoded_lines = 0;            /* # lines encoded     */
  654. X    char buffer[SLEN];            /* file reading buffer */
  655. X
  656. X    while (fgets(buffer, SLEN, source) != NULL) {
  657. X      if (buffer[0] == '[') {
  658. X        if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
  659. X          crypted = TRUE;
  660. X        else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
  661. X          crypted = FALSE;
  662. X        else if ((strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
  663. X              || (strncmp(buffer, DONT_SAVE2, strlen(DONT_SAVE2)) == 0)) {
  664. X          if(copy) break;  /* saved copy doesn't want anything after this */
  665. X          else continue;   /* next line? */
  666. X        }
  667. X      }
  668. X      else if (crypted) {
  669. X        if (batch_only) {
  670. X          printf(
  671. X        "Sorry. Cannot send encrypted mail in \"batch mode\".\n\r");
  672. X          leave();
  673. X        } else if (! gotten_key++)
  674. X          getkey(ON);
  675. X        else if (! encoded_lines)
  676. X          get_key_no_prompt();        /* reinitialize.. */
  677. X        encode(buffer);
  678. X        encoded_lines++;
  679. X      }
  680. X
  681. X      if (copy && (strncmp(buffer, "From ", 5) == 0))
  682. X        /* Add in the > to a From on our copy */
  683. X        fprintf(dest, ">%s", buffer);
  684. X
  685. X      else if (!copy && strcmp(buffer, ".\n") == 0)
  686. X        /* Because some mail transport agents take a lone period to
  687. X         * mean EOF, we add a blank space on outbound message.
  688. X         */
  689. X        fputs(". \n", dest);
  690. X        else
  691. X          fputs(buffer, dest);
  692. X    } 
  693. X    if (copy) fputs("\n", dest);    /* ensure a blank line at the end */
  694. X}
  695. X
  696. Xint
  697. Xverify_bounceback()
  698. X{
  699. X    char    ch;
  700. X
  701. X    /** Ensure the user wants to have a bounceback copy too.  (This is
  702. X        only called on messages that are greater than the specified 
  703. X        threshold hops and NEVER for non-uucp addresses.... Returns
  704. X        TRUE iff the user wants to bounce a copy back.... 
  705. X     **/
  706. X
  707. X    MoveCursor(LINES,0);
  708. X    CleartoEOLN();
  709. X    PutLine1(LINES,0, 
  710. X          "\"Bounce\" a copy off the remote machine? (y/n) y%c",
  711. X          BACKSPACE);
  712. X    fflush(stdin);    /* wait for answer! */
  713. X    fflush(stdout);
  714. X    ch = ReadCh();
  715. X    if (tolower(ch) != 'y') { 
  716. X      Write_to_screen("No.", 0);
  717. X      fflush(stdout);
  718. X      return(FALSE);
  719. X    }
  720. X    Write_to_screen("Yes.", 0);
  721. X    fflush(stdout);
  722. X
  723. X    return(TRUE);
  724. X}
  725. SHAR_EOF
  726. echo "File src/mailmsg2.c is complete"
  727. chmod 0444 src/mailmsg2.c || echo "restore of src/mailmsg2.c fails"
  728. echo "x - extracting src/mailtime.c (Text)"
  729. sed 's/^X//' << 'SHAR_EOF' > src/mailtime.c &&
  730. X
  731. Xstatic char rcsid[] = "@(#)$Id: mailtime.c,v 2.6 89/03/25 21:46:46 syd Exp $";
  732. X
  733. X/*******************************************************************************
  734. X *  The Elm Mail System  -  $Revision: 2.6 $   $State: Exp $
  735. X *
  736. X *             Copyright (c) 1986, 1987 Dave Taylor
  737. X *             Copyright (c) 1988, 1989 USENET Community Trust
  738. X *******************************************************************************
  739. X * Bug reports, patches, comments, suggestions should be sent to:
  740. X *
  741. X *    Syd Weinstein, Elm Coordinator
  742. X *    elm@dsinc.UUCP            dsinc!elm
  743. X *
  744. X *******************************************************************************
  745. X * $Log:    mailtime.c,v $
  746. X * Revision 2.6  89/03/25  21:46:46  syd
  747. X * Initial 2.2 Release checkin
  748. X * 
  749. X *
  750. X ******************************************************************************/
  751. X
  752. X/** This set of routines is used to figure out when the user last read
  753. X    their mail and to also figure out if a given message is new or not.
  754. X
  755. X**/
  756. X
  757. X#include "headers.h"
  758. X
  759. X#include <sys/types.h>
  760. X#include <sys/stat.h>
  761. X#ifdef BSD
  762. X#  ifdef TMINSYS
  763. X#    include <sys/time.h>
  764. X#  else
  765. X#    include <time.h>
  766. X#    include <sys/timeb.h>
  767. X#  endif
  768. X#else
  769. X#  include <time.h>
  770. X#endif
  771. X
  772. Xresolve_received(entry)
  773. Xstruct header_rec *entry;
  774. X{
  775. X    /** Entry has the data for computing the time and date the 
  776. X        message was received.  Fix it and return **/
  777. X
  778. X    switch (tolower(entry->month[0])) {
  779. X      case 'j' : if (tolower(entry->month[1]) == 'a')
  780. X               entry->received.month = JANUARY;
  781. X             else if (tolower(entry->month[2]) == 'n')
  782. X                   entry->received.month = JUNE;
  783. X             else
  784. X                   entry->received.month = JULY;
  785. X                 break;
  786. X      case 'f' : entry->received.month = FEBRUARY;
  787. X              break;
  788. X      case 'm' : if (tolower(entry->month[2]) == 'r')
  789. X                   entry->received.month = MARCH;
  790. X             else
  791. X               entry->received.month = MAY;
  792. X                 break;
  793. X      case 'a' : if (tolower(entry->month[1]) == 'p')
  794. X                   entry->received.month = APRIL;
  795. X                 else
  796. X                   entry->received.month = AUGUST;
  797. X             break;
  798. X      case 's' : entry->received.month = SEPTEMBER;
  799. X             break;
  800. X      case 'o' : entry->received.month = OCTOBER;
  801. X             break;
  802. X      case 'n' : entry->received.month = NOVEMBER;
  803. X               break;
  804. X      case 'd' : entry->received.month = DECEMBER;
  805. X             break;
  806. X    }
  807. X
  808. X    sscanf(entry->day, "%d", &(entry->received.day));
  809. X
  810. X    sscanf(entry->year, "%d", &(entry->received.year));
  811. X    if (entry->received.year > 100) entry->received.year -= 1900;
  812. X
  813. X    sscanf(entry->time, "%d:%d", &(entry->received.hour),
  814. X           &(entry->received.minute));
  815. X}
  816. SHAR_EOF
  817. chmod 0444 src/mailtime.c || echo "restore of src/mailtime.c fails"
  818. echo "x - extracting src/mkhdrs.c (Text)"
  819. sed 's/^X//' << 'SHAR_EOF' > src/mkhdrs.c &&
  820. X
  821. Xstatic char rcsid[] = "@(#)$Id: mkhdrs.c,v 2.7 89/03/25 21:46:48 syd Exp $";
  822. X
  823. X/*******************************************************************************
  824. X *  The Elm Mail System  -  $Revision: 2.7 $   $State: Exp $
  825. X *
  826. X *             Copyright (c) 1986, 1987 Dave Taylor
  827. X *             Copyright (c) 1988, 1989 USENET Community Trust
  828. X *******************************************************************************
  829. X * Bug reports, patches, comments, suggestions should be sent to:
  830. X *
  831. X *    Syd Weinstein, Elm Coordinator
  832. X *    elm@dsinc.UUCP            dsinc!elm
  833. X *
  834. X *******************************************************************************
  835. X * $Log:    mkhdrs.c,v $
  836. X * Revision 2.7  89/03/25  21:46:48  syd
  837. X * Initial 2.2 Release checkin
  838. X * 
  839. X *
  840. X ******************************************************************************/
  841. X
  842. X/** This contains all the header generating routines for the ELM
  843. X    program.
  844. X
  845. X**/
  846. X
  847. X#include "headers.h"
  848. X
  849. Xextern char in_reply_to[SLEN];
  850. X
  851. Xchar *strcpy();
  852. Xunsigned long sleep();
  853. X
  854. Xgenerate_reply_to(msg)
  855. Xint msg;
  856. X{
  857. X    /** Generate an 'in-reply-to' message... **/
  858. X    char buffer[SLEN];
  859. X
  860. X
  861. X    if (msg == -1)        /* not a reply! */
  862. X      in_reply_to[0] = '\0';
  863. X    else {
  864. X      if (chloc(headers[msg]->from, '!') != -1)
  865. X        tail_of(headers[msg]->from, buffer, 0);
  866. X      else
  867. X        strcpy(buffer, headers[msg]->from);
  868. X      sprintf(in_reply_to, "%s; from \"%s\" at %s %s, %s %s",
  869. X          headers[msg]->messageid,
  870. X          buffer,
  871. X          headers[msg]->month,
  872. X          headers[msg]->day,
  873. X          headers[msg]->year,
  874. X          headers[msg]->time);
  875. X    }
  876. X}
  877. X
  878. Xadd_mailheaders(filedesc)
  879. XFILE *filedesc;
  880. X{
  881. X    /** Add the users .mailheaders file if available.  Allow backquoting 
  882. X        in the file, too, for fortunes, etc...*shudder*
  883. X    **/
  884. X
  885. X    FILE *fd;
  886. X    char filename[SLEN], buffer[SLEN];
  887. X
  888. X    sprintf(filename, "%s/%s", home, mailheaders);
  889. X
  890. X    if ((fd = fopen(filename, "r")) != NULL) {
  891. X      while (fgets(buffer, SLEN, fd) != NULL)
  892. X        if (strlen(buffer) < 2) {
  893. X          dprint(2, (debugfile,
  894. X             "Strlen of line from .elmheaders is < 2 (write_header_info)"));
  895. X          error1("Warning: blank line in %s ignored!", filename);
  896. X          sleep(2);
  897. X        }
  898. X        else if (occurances_of(BACKQUOTE, buffer) >= 2) 
  899. X          expand_backquote(buffer, filedesc);
  900. X        else 
  901. X          fprintf(filedesc, "%s", buffer);
  902. X
  903. X        fclose(fd);
  904. X    }
  905. X}
  906. X
  907. Xexpand_backquote(buffer, filedesc)
  908. Xchar *buffer;
  909. XFILE *filedesc;
  910. X{
  911. X    /** This routine is called with a line of the form:
  912. X        Fieldname: `command`
  913. X        and is expanded accordingly..
  914. X    **/
  915. X
  916. X    FILE *fd;
  917. X    char command[SLEN], command_buffer[SLEN], fname[SLEN],
  918. X         prefix[SLEN];
  919. X    register int i, j = 0;
  920. X
  921. X    for (i=0; buffer[i] != BACKQUOTE; i++)
  922. X      prefix[j++] = buffer[i];
  923. X    prefix[j] = '\0';
  924. X
  925. X    j = 0;
  926. X
  927. X    for (i=chloc(buffer, BACKQUOTE)+1; buffer[i] != BACKQUOTE;i++)
  928. X      command[j++] = buffer[i];
  929. X    command[j] = '\0';
  930. X
  931. X    sprintf(fname,"%s%d", temp_print, getpid());
  932. X
  933. X    sprintf(command_buffer, "%s > %s", command, fname);
  934. X
  935. X    system_call(command_buffer, SH, FALSE);
  936. X
  937. X    if ((fd = fopen(fname, "r")) == NULL) {
  938. X      error1("Backquoted command \"%s\" in elmheaders failed.", command);
  939. X      return;    
  940. X    }
  941. X
  942. X    /* If we get a line that is less than 80 - length of prefix then we
  943. X       can toss it on the same line, otherwise, simply prepend each line
  944. X       *starting with this line* with a leading tab and cruise along */
  945. X
  946. X    if (fgets(command_buffer, SLEN, fd) == NULL) 
  947. X      fprintf(filedesc, prefix);
  948. X    else {
  949. X      if (strlen(command_buffer) + strlen(prefix) < 80) 
  950. X        fprintf(filedesc, "%s%s", prefix, command_buffer);
  951. X      else
  952. X        fprintf(filedesc, "%s\n\t%s", prefix, command_buffer);
  953. X      
  954. X      while (fgets(command_buffer, SLEN, fd) != NULL) 
  955. X        fprintf(filedesc, "\t%s", command_buffer);
  956. X    
  957. X      fclose(fd);
  958. X    }
  959. X
  960. X    unlink(fname);    /* don't leave the temp file laying around! */
  961. X}
  962. SHAR_EOF
  963. chmod 0444 src/mkhdrs.c || echo "restore of src/mkhdrs.c fails"
  964. echo "x - extracting src/newmbox.c (Text)"
  965. sed 's/^X//' << 'SHAR_EOF' > src/newmbox.c &&
  966. X
  967. Xstatic char rcsid[] = "@(#)$Id: newmbox.c,v 2.35 89/03/29 09:07:09 syd Exp $";
  968. X
  969. X/*******************************************************************************
  970. X *  The Elm Mail System  -  $Revision: 2.35 $   $State: Exp $
  971. X *
  972. X *             Copyright (c) 1988, USENET Community Trust
  973. X *             Copyright (c) 1988, 1989 USENET Community Trust
  974. X *******************************************************************************
  975. X * Bug reports, patches, comments, suggestions should be sent to:
  976. X *
  977. X *    Syd Weinstein, Elm Coordinator
  978. X *    elm@dsinc.UUCP            dsinc!elm
  979. X *
  980. X *******************************************************************************
  981. X * $Log:    newmbox.c,v $
  982. X * Revision 2.35  89/03/29  09:07:09  syd
  983. X * Fix problem with assuming headers start file
  984. X * From: Rob
  985. X * 
  986. X * Revision 2.34  89/03/25  21:46:49  syd
  987. X * Initial 2.2 Release checkin
  988. X * 
  989. X *
  990. X ******************************************************************************/
  991. X
  992. X/**  read new folder **/
  993. X
  994. X#include <ctype.h>
  995. X#include "headers.h"
  996. X
  997. X#ifdef BSD
  998. X#undef tolower        /* we have our own "tolower" routine instead! */
  999. X#endif
  1000. X
  1001. X#include <sys/types.h>        
  1002. X#include <sys/stat.h>
  1003. X#include <errno.h>
  1004. X
  1005. X#ifdef BSD            /* Berkeley has library elsewhere... */
  1006. X#  ifdef TMINSYS
  1007. X#    include <sys/time.h>
  1008. X#  else
  1009. X#    include <time.h>
  1010. X#  endif
  1011. Xchar *malloc(), *realloc();
  1012. X#else
  1013. X#  include <time.h>
  1014. X#endif
  1015. X
  1016. Xextern int errno;
  1017. X
  1018. Xchar *error_name(), *error_description();
  1019. Xchar *malloc(), *realloc(), *strcpy(), *strncpy(), *strrchr(), *strchr();
  1020. Xunsigned long sleep();
  1021. Xvoid rewind();
  1022. Xvoid exit();
  1023. Xlong bytes();
  1024. X
  1025. Xint
  1026. Xnewmbox(new_file, adds_only)
  1027. Xchar *new_file;
  1028. Xint adds_only;
  1029. X{
  1030. X    /** Read a folder.
  1031. X
  1032. X        new_file    - name of folder  to read. It is up to the calling
  1033. X              function to make sure that the file can be
  1034. X              read by the user. This is not checked in this
  1035. X              function. The reason why it is not checked here
  1036. X              is due to the situation where the user wants to
  1037. X              change folders: the new folder must be checked
  1038. X              for access *before* leaving the old one, which
  1039. X              is before this function gets called.
  1040. X        adds_only    - set if we only want to read newly added messages to
  1041. X                same old folder.
  1042. X
  1043. X    **/
  1044. X
  1045. X    int  same_file;
  1046. X    int  new_folder_type;
  1047. X    char new_tempfile[SLEN], buffer[SLEN];
  1048. X
  1049. X    /* determine type of new mailfile and calculate temp file name */
  1050. X    if((new_folder_type = get_folder_type(new_file)) == SPOOL)
  1051. X      mk_temp_mail_fn(new_tempfile, new_file);
  1052. X    else
  1053. X      *new_tempfile = '\0';
  1054. X
  1055. X    /* determine whether we are changing files */
  1056. X    same_file = !(strcmp(new_file, cur_folder));
  1057. X
  1058. X    /* If we are changing files and we are changing to a spool file,
  1059. X     * make sure there isn't a temp file for it, because if
  1060. X     * there is, someone else is using ELM to read the new file,
  1061. X     * and we don't want to be reading it at the same time.
  1062. X     */
  1063. X    if((new_folder_type == SPOOL) && (!same_file)) {
  1064. X      if (access(new_tempfile, ACCESS_EXISTS) != -1) {
  1065. X        if(folder_type != NO_NAME) ClearScreen();
  1066. X        Centerline(15,
  1067. X          "Hey! An instantiation of ELM is already reading this mail!");
  1068. X        Centerline(17,
  1069. X          "If this is in error, then you'll need to remove the file:");
  1070. X        Centerline(18, new_tempfile);
  1071. X        MoveCursor(LINES, 0);  /* so shell prompt upon exit is on newline */
  1072. X        silently_exit();
  1073. X      }
  1074. X    }
  1075. X
  1076. X    /* If we were reading a spool file and we are not just reading
  1077. X     * in the additional new messages to the same file, we need to
  1078. X     * remove the corresponding tempfile.
  1079. X     */
  1080. X
  1081. X    if((folder_type == SPOOL) && !adds_only) {
  1082. X      if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
  1083. X        if (unlink(cur_tempfolder) != 0) {
  1084. X          error2("Sorry, can't unlink the temp file %s [%s]!\n\r",
  1085. X            cur_tempfolder, error_name(errno));
  1086. X          silently_exit();
  1087. X        }
  1088. X      }
  1089. X    }
  1090. X
  1091. X    /* Okay! Now establish this new file as THE file */
  1092. X    strcpy(cur_folder, new_file);
  1093. X    folder_type = new_folder_type;
  1094. X    strcpy(cur_tempfolder, new_tempfile);
  1095. X
  1096. X    clear_error();
  1097. X    clear_central_message();
  1098. X
  1099. X    if (mailfile != NULL)
  1100. X      (void) fclose(mailfile);  /* close it first, to avoid too many open */
  1101. X
  1102. X    if ((mailfile = fopen(cur_folder,"r")) == NULL)  {
  1103. X      mailfile_size = 0;        /* must be empty folder */
  1104. X      message_count = 0;
  1105. X    } else {
  1106. X      read_headers(adds_only);
  1107. X    }
  1108. X
  1109. X    if(!same_file)        /* limit mode off if this is a new file */
  1110. X      selected = 0;
  1111. X
  1112. X    dprint(1, (debugfile,
  1113. X      "New folder %s type %s temp file %s (%s)\n", cur_folder, 
  1114. X      (folder_type == SPOOL ? "spool" : "non-spool"),
  1115. X      (*cur_tempfolder ? cur_tempfolder : "none"), "newmbox"));
  1116. X
  1117. X    return(0);
  1118. X}
  1119. X
  1120. Xint
  1121. Xget_folder_type(filename)
  1122. Xchar *filename;
  1123. X{
  1124. X    /** returns the type of mailfile filename is
  1125. X        NO_NAME = no name
  1126. X        SPOOL = consisting only of mailhome plus base file name
  1127. X            (no intervening directory name)
  1128. X        NON_SPOOL = a name that is not SPOOL type above
  1129. X     **/
  1130. X
  1131. X    char *last_slash;
  1132. X
  1133. X    /* if filename is null or is of zero length */
  1134. X    if((filename == NULL) || (*filename == '\0'))
  1135. X      return(NO_NAME);
  1136. X
  1137. X    /* if filename begins with mailhome,
  1138. X     * and there is a slash in filename,
  1139. X     * and there is a filename after it (i.e. last slash is not last char),
  1140. X     * and the last character of mailhome is last slash in filename,
  1141. X     * it's a spool file .
  1142. X     */
  1143. X    if((first_word(filename, mailhome)) &&
  1144. X      ((last_slash = strrchr(filename, '/')) != NULL) &&
  1145. X      (*(last_slash+1) != '\0') &&
  1146. X      (filename + strlen(mailhome) - 1 == last_slash))
  1147. X        return(SPOOL);
  1148. X    /* if file name == default mailbox, its a spool file also
  1149. X     * even if its not in the spool directory. (SVR4)
  1150. X     */
  1151. X    if (strcmp(filename, defaultfile) == 0)
  1152. X        return(SPOOL);
  1153. X
  1154. X    return(NON_SPOOL);
  1155. X}
  1156. X
  1157. Xmk_temp_mail_fn(tempfn, mbox)
  1158. Xchar *tempfn, *mbox;
  1159. X{
  1160. X    /** create in tempfn the name of the temp file corresponding to
  1161. X        mailfile mbox. Mbox is presumed to be a file in mailhome;
  1162. X        Strangeness may result if it is not!
  1163. X     **/
  1164. X
  1165. X    char *cp;    /* will point to '/' preceding filename part of mbox */
  1166. X    strcpy(tempfn, temp_mbox);
  1167. X    if((cp = strrchr(mbox, '/')) != NULL)
  1168. X      strcat(tempfn, cp+1);
  1169. X}
  1170. X
  1171. Xint
  1172. Xread_headers(add_new_only)
  1173. Xint add_new_only;
  1174. X{
  1175. X    /** Reads the headers into the headers[] array and leaves the
  1176. X        file rewound for further I/O requests.   If the file being
  1177. X        read is a mail spool file (ie incoming) then it is copied to
  1178. X        a temp file and closed, to allow more mail to arrive during 
  1179. X        the elm session.  If 'add_new_only' is set, the program will copy
  1180. X        the status flags from the previous data structure to the new 
  1181. X        one if possible and only read in newly added messages.
  1182. X    **/
  1183. X
  1184. X    FILE *temp;
  1185. X    struct header_rec *current_header = NULL;
  1186. X    char buffer[LONG_STRING], *c;
  1187. X    long fbytes = 0L, line_bytes = 0L;
  1188. X    register int line = 0, count = 0, another_count,
  1189. X      subj = 0, copyit = 0, in_header = 0;
  1190. X    int count_x, count_y = 17, new_messages = 0, err;
  1191. X    int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE;
  1192. X
  1193. X    static int first_read = 0;
  1194. X
  1195. X    if (folder_type == SPOOL) {
  1196. X      lock(INCOMING);    /* ensure no mail arrives while we do this! */
  1197. X      if (! add_new_only) {
  1198. X        if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
  1199. X          /* Hey!  What the hell is this?  The temp file already exists? */
  1200. X          /* Looks like a potential clash of processes on the same file! */
  1201. X          unlock();                     /* so remove lock file! */
  1202. X          error("What's this?  The temp folder already exists??");
  1203. X          sleep(2);
  1204. X          error("Ahhhh... I give up.");
  1205. X          silently_exit();    /* leave without tampering with it! */
  1206. X        }
  1207. X        if ((temp = fopen(cur_tempfolder,"w")) == NULL) {
  1208. X         err = errno;
  1209. X         unlock();    /* remove lock file! */
  1210. X         Raw(OFF);
  1211. X         Write_to_screen(
  1212. X             "\n\rCouldn't open file %s for use as temp file.\n\r",
  1213. X             1, cur_tempfolder);
  1214. X         Write_to_screen("** %s - %s. **\n\r", 2,
  1215. X             error_name(err), error_description(err));
  1216. X         dprint(1, (debugfile,
  1217. X                "Error: Couldn't open file %s as temp mbox.  errno %s (%s)\n",
  1218. X             cur_tempfolder, error_name(err), "read_headers"));
  1219. X         leave();
  1220. X        }
  1221. X       copyit++;
  1222. X       chown(cur_tempfolder, userid, groupid);
  1223. X       chmod(cur_tempfolder, 0700);    /* shut off file for other people! */
  1224. X     }
  1225. X     else {
  1226. X       if ((temp = fopen(cur_tempfolder,"a")) == NULL) {
  1227. X         err = errno;
  1228. X         unlock();    /* remove lock file! */
  1229. X         Raw(OFF);
  1230. X         Write_to_screen(
  1231. X             "\n\rCouldn't reopen file %s for use as temp file.\n\r",
  1232. X             1, cur_tempfolder);
  1233. X         Write_to_screen("** %s - %s. **\n\r", 2,
  1234. X             error_name(err), error_description(err));
  1235. X         dprint(1, (debugfile, 
  1236. X                "Error: Couldn't reopen file %s as temp mbox.  errno %s (%s)\n",
  1237. X             cur_tempfolder, error_name(err), "read_headers"));
  1238. X         emergency_exit();
  1239. X        }
  1240. X       copyit++;
  1241. X      }
  1242. X    }
  1243. X
  1244. X    if (! first_read++) {
  1245. X      ClearLine(LINES-1);
  1246. X      ClearLine(LINES);
  1247. X      if (add_new_only)
  1248. X        PutLine2(LINES, 0, "Reading in %s, message: %d", cur_folder, 
  1249. X             message_count);
  1250. X      else
  1251. X        PutLine1(LINES, 0, "Reading in %s, message: 0", cur_folder);
  1252. X      count_x = LINES;
  1253. X          count_y = 22 + strlen(cur_folder);
  1254. X    }
  1255. X    else {
  1256. X      count_x = LINES-2;
  1257. X      PutLine0(LINES-2, 0, "Reading message: 0");
  1258. X    }
  1259. X
  1260. X    if (add_new_only) {
  1261. X       if (fseek(mailfile, mailfile_size, 0) == -1) {
  1262. X         err = errno;
  1263. X         Write_to_screen(
  1264. X        "\n\rCouldn't seek to %ld (end of folder) in %s!\n\r", 2,
  1265. X             mailfile_size, cur_folder);    
  1266. X         Write_to_screen("** %s - %s. **\n\r", 2,
  1267. X             error_name(err), error_description(err));
  1268. X         dprint(1, (debugfile,
  1269. X     "Error: Couldn't seek to end of folder %s: (offset %ld) Errno %s (%s)\n",
  1270. X            cur_folder, mailfile_size, error_name(err), "read_headers"));
  1271. X         emergency_exit();
  1272. X       }
  1273. X       count = message_count;        /* next available  */
  1274. X       fbytes = mailfile_size;        /* start correctly */
  1275. X    }
  1276. X
  1277. X    /** find the size of the folder then unlock the file **/
  1278. X
  1279. X    mailfile_size = bytes(cur_folder);
  1280. X    unlock();
  1281. X
  1282. X    /** now let's copy it all across accordingly... **/
  1283. X
  1284. X    while (fbytes < mailfile_size) {
  1285. X
  1286. X      if (fgets(buffer, LONG_STRING, mailfile) == NULL) break;
  1287. X
  1288. X      if (copyit) fputs(buffer, temp);
  1289. X      line_bytes = (long) strlen(buffer); 
  1290. X
  1291. X      /* Fix below to increment line count ONLY if we got a full line.
  1292. X       * Input lines longer than the fgets buffer size would
  1293. X       * get counted each time a subsequent part of them was
  1294. X       * read in. This meant that when the faulty line count was used
  1295. X       * to display the message, part of the next message
  1296. X       * was displayed at the end of the message.
  1297. X       */
  1298. X      if(buffer[strlen(buffer)-1] == '\n') line++;
  1299. X
  1300. X      if (fbytes == 0L || first_line) {     /* first line of file... */    
  1301. X        if (folder_type == SPOOL) {
  1302. X          if (first_word(buffer, "Forward to ")) {
  1303. X            set_central_message("Mail being forwarded to %s", 
  1304. X                   (char *) (buffer + 11));
  1305. X            forwarding_mail = TRUE;
  1306. X          }
  1307. X        }
  1308. X
  1309. X        /** flush leading blank lines before next test... **/
  1310. X        if (strlen(buffer) == 1) {
  1311. X          fbytes++;
  1312. X          continue;    
  1313. X        }
  1314. X        else
  1315. X          first_line = FALSE;
  1316. X              
  1317. X        if (! first_word(buffer, "From ") && !forwarding_mail) {
  1318. X          PutLine0(LINES, 0,
  1319. X          "\n\rFolder is corrupt!!  I can't read it!!\n\r\n\r");
  1320. X          fflush(stderr);
  1321. X          dprint(1, (debugfile, 
  1322. X               "\n\n**** First mail header is corrupt!! ****\n\n"));
  1323. X          dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
  1324. X              mail_only++;    /* to avoid leave() cursor motion */
  1325. X              leave();
  1326. X        }
  1327. X      }
  1328. X
  1329. X      if (first_word(buffer,"From ")) {
  1330. X    
  1331. X        /** allocate new header pointers, if needed... **/
  1332. X
  1333. X        if (count >= max_headers) {
  1334. X          struct header_rec **new_headers;
  1335. X          int new_max;
  1336. X
  1337. X          new_max = max_headers + KLICK;
  1338. X          if (max_headers == 0) {
  1339. X        new_headers = (struct header_rec **)
  1340. X          malloc(new_max * sizeof(struct header_rec *));
  1341. X          }
  1342. X          else {
  1343. X        new_headers = (struct header_rec **)
  1344. X          realloc(headers, new_max * sizeof(struct header_rec *));
  1345. X          }
  1346. X          if (new_headers == NULL) {
  1347. X            error1(
  1348. X      "\n\r\n\rCouldn't allocate enough memory! Message #%d.\n\r\n\r",
  1349. X            count);
  1350. X            leave();
  1351. X          }
  1352. X          headers = new_headers;
  1353. X          while (max_headers < new_max)
  1354. X        headers[max_headers++] = NULL;
  1355. X        }
  1356. X          
  1357. X        /** allocate new header structure, if needed... **/
  1358. X
  1359. X        if (headers[count] == NULL) {
  1360. X          struct header_rec *h;
  1361. X
  1362. X          if ((h = (struct header_rec *)
  1363. X            malloc(sizeof(struct header_rec))) == NULL) {
  1364. X            error1(
  1365. X      "\n\r\n\rCouldn't allocate enough memory! Message #%d.\n\r\n\r",
  1366. X            count);
  1367. X            leave();
  1368. X          }
  1369. X          headers[count] = h;
  1370. X        }
  1371. X
  1372. X        if (real_from(buffer, headers[count])) {
  1373. X          current_header = headers[count];
  1374. X
  1375. X          current_header->offset = (long) fbytes;
  1376. X          current_header->index_number = count+1;
  1377. X          if (! add_new_only || count >= message_count)  {
  1378. X        /* set default status - always 'visible'  - and
  1379. X         * if a spool file, presume 'new', otherwise
  1380. X         * 'read', for the time being until overridden
  1381. X         * by a Status: header.
  1382. X         * We presume 'read' for nonspool mailfile messages
  1383. X         * to be compatible messages stored with older versions of elm,
  1384. X         * which didn't support a Status: header.
  1385. X         */
  1386. X        if(folder_type == SPOOL)
  1387. X          current_header->status = VISIBLE | NEW | UNREAD;
  1388. X        else
  1389. X          current_header->status = VISIBLE;
  1390. X          }
  1391. X
  1392. X          strcpy(current_header->subject, "");    /* clear subj    */
  1393. X          strcpy(current_header->to, "");        /* clear to    */
  1394. X          strcpy(current_header->mailx_status, "");    /* clear status flags    */
  1395. X          current_header->encrypted = 0;        /* clear encrypted */
  1396. X          current_header->exit_disposition = UNSET;
  1397. X          current_header->status_chgd = FALSE;
  1398. X
  1399. X          /* Set the number of lines for the _preceding_ message,
  1400. X           * but only if there was a preceding message and
  1401. X           * only if it wasn't calculated already. It would
  1402. X           * have been calculated already if we are only
  1403. X           * reading headers of new messages that have just arrived,
  1404. X           * and the preceding message was one of the old ones.
  1405. X           */
  1406. X          if ((count) && (!add_new_only || count > message_count))
  1407. X            headers[count-1]->lines = line;
  1408. X
  1409. X          count++;
  1410. X          subj = 0;
  1411. X          line = 0;
  1412. X          in_header = 1;
  1413. X          PutLine1(count_x, count_y, "%d", count);
  1414. X        } else if (count == 0) {
  1415. X          /* if this is the first "From" in file but the "From" line is
  1416. X           * not of the proper format, we've got a corrupt folder.
  1417. X           */
  1418. X          PutLine0(LINES, 0,
  1419. X          "\n\rFolder is corrupt!!  I can't read it!!\n\r\n\r");
  1420. X          fflush(stderr);
  1421. X          dprint(1, (debugfile, 
  1422. X               "\n\n**** First mail header is corrupt!! ****\n\n"));
  1423. X          dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
  1424. X              mail_only++;    /* to avoid leave() cursor motion */
  1425. X              leave();
  1426. X        }
  1427. X      }
  1428. X      else if (in_header) {
  1429. X        if (first_word(buffer,">From:"))
  1430. X          parse_arpa_who(buffer, current_header->from, FALSE);
  1431. X        else if (first_word(buffer,">From")) 
  1432. X          forwarded(buffer, current_header); /* return address */
  1433. X        else if (first_word(buffer,"Subject:") ||
  1434. X             first_word(buffer,"Subj:") ||
  1435. X             first_word(buffer,"Re:")) {
  1436. X          if (! subj++) {
  1437. X            remove_first_word(buffer);
  1438. X            copy_sans_escape(current_header->subject, buffer, STRING);
  1439. X        remove_possible_trailing_spaces(current_header->subject);
  1440. X          }
  1441. X        }
  1442. X        else if (first_word(buffer,"From:"))
  1443. X          parse_arpa_who(buffer, current_header->from, FALSE);
  1444. X
  1445. X        else if (first_word(buffer, "Message-Id:") ||
  1446. X             first_word(buffer, "Message-ID:")) {
  1447. X          buffer[strlen(buffer)-1] = '\0';
  1448. X          strcpy(current_header->messageid,
  1449. X             (char *) buffer + 12);
  1450. X        }
  1451. X
  1452. X        else if (first_word(buffer, "Expires:"))
  1453. X          process_expiration_date((char *) buffer + 9, 
  1454. X                      &(current_header->status));
  1455. X        
  1456. X        /** when it was sent... **/
  1457. X
  1458. X        else if (first_word(buffer, "Date:")) 
  1459. X          parse_arpa_date(buffer, current_header);
  1460. X
  1461. X        /** some status things about the message... **/
  1462. X
  1463. X        else if (first_word(buffer, "Priority:") || 
  1464. X             first_word(buffer, "Importance: 2"))
  1465. X          current_header->status |= URGENT;
  1466. X        else if (first_word(buffer, "Sensitivity: 2"))
  1467. X          current_header->status |= PRIVATE;
  1468. X        else if (first_word(buffer, "Sensitivity: 3"))
  1469. X          current_header->status |= CONFIDENTIAL;
  1470. X        else if (first_word(buffer, "Content-Type: mailform"))
  1471. X          current_header->status |= FORM_LETTER;
  1472. X        else if (first_word(buffer, "Action:"))
  1473. X          current_header->status |= ACTION;
  1474. X
  1475. X        /** next let's see if it's to us or not... **/
  1476. X
  1477. X        else if (first_word(buffer, "To:")) {
  1478. X          in_to_list = TRUE;
  1479. X          current_header->to[0] = '\0';    /* nothing yet */
  1480. X          figure_out_addressee((char *) buffer +3, 
  1481. X                   current_header->to);
  1482. X        }
  1483. X        else if (first_word(buffer, "Status:")) {
  1484. X          remove_first_word(buffer);
  1485. X          strncpy(current_header->mailx_status, buffer, WLEN-1);
  1486. X          current_header->mailx_status[WLEN-1] ='\0';
  1487. X
  1488. X          c = strchr(current_header->mailx_status, '\n');
  1489. X          if (c != NULL)
  1490. X        *c = '\0';
  1491. X          remove_possible_trailing_spaces(current_header->mailx_status);
  1492. X
  1493. X          /* Okay readjust the status. If there's an 'R', message
  1494. X           * is read; if there is no 'R' but there is an 'O', message
  1495. X           * is unread. In any case it isn't new because a new message
  1496. X           * wouldn't have a Status: header.
  1497. X           */
  1498. X          if (strchr(current_header->mailx_status, 'R') != NULL)
  1499. X        current_header->status = VISIBLE;
  1500. X          else if (strchr(current_header->mailx_status, 'O') != NULL)
  1501. X        current_header->status = VISIBLE | UNREAD;
  1502. X        }
  1503. X
  1504. X        else if (buffer[0] == LINE_FEED || buffer[0] == '\0') {
  1505. X          if (in_header) {
  1506. X            in_header = 0;    /* in body of message! */
  1507. X            fix_date(current_header);
  1508. X          }
  1509. X        }
  1510. X        else if (in_header) {
  1511. X           if ((!whitespace(buffer[0])) && strchr(buffer, ':') == NULL) {
  1512. X            in_header = 0;    /* in body of message! */
  1513. X            fix_date(current_header);
  1514. X          }
  1515. X        }
  1516. X        else if (in_to_list == TRUE) {
  1517. X          if (whitespace(buffer[0]))
  1518. X            figure_out_addressee(buffer, current_header->to);
  1519. X          else in_to_list = FALSE;
  1520. X        }
  1521. X      }
  1522. X      if (!in_header && first_word(buffer, START_ENCODE))
  1523. X        current_header->encrypted = 1;
  1524. X      fbytes += (long) line_bytes;
  1525. X    }
  1526. X
  1527. X    if (count)
  1528. X      headers[count-1]->lines = line + 1;
  1529. X
  1530. X    if (folder_type == SPOOL) {
  1531. X      unlock();    /* remove lock file! */
  1532. X      fclose(mailfile);
  1533. X      fclose(temp);
  1534. X      if ((mailfile = fopen(cur_tempfolder,"r")) == NULL) {
  1535. X        err = errno;
  1536. X        MoveCursor(LINES,0);
  1537. X        Raw(OFF);
  1538. X        Write_to_screen(
  1539. X           "\n\rAugh! Couldn't reopen %s as temp file.\n\r",
  1540. X               1, cur_tempfolder);
  1541. X        Write_to_screen("** %s - %s. **\n\r", 2, error_name(err),
  1542. X           error_description(err));
  1543. X        dprint(1, (debugfile,
  1544. X          "Error: Reopening %s as temp file failed!  errno %s (%s)\n",
  1545. X               cur_tempfolder, error_name(errno), "read_headers"));
  1546. X        leave();
  1547. X      }
  1548. X    }
  1549. X    else 
  1550. X          rewind(mailfile);
  1551. X
  1552. X    /* Sort folder *before* we establish the current message, so that
  1553. X     * the current message is based on the post-sort order.
  1554. X     * Note that we have to set the global variable message_count
  1555. X     * before the sort for the sort to correctly keep the correct
  1556. X     * current message if we are only adding new messages here. */
  1557. X
  1558. X    message_count = count;
  1559. X    sort_mailbox(count, 1);
  1560. X
  1561. X    /* Now lets figure what the current message should be.
  1562. X     * If we are only reading in newly added messages from a mailfile
  1563. X     * that already had some messages, current should remain the same.
  1564. X     * If we have a folder of no messages, current should be zero.
  1565. X     * Otherwise, if we have point_to_new on then the current message
  1566. X     * is the first message of status NEW if there is one.
  1567. X     * If we don't have point_to_new on or if there are no messages of
  1568. X     * of status NEW, then the current message is the first message.
  1569. X     */
  1570. X    if(!(add_new_only && current != 0)) {
  1571. X      if(count == 0)
  1572. X        current = 0;
  1573. X      else {
  1574. X        current = 1;
  1575. X        if (point_to_new) {
  1576. X          for(another_count = 0; another_count < count; another_count++) {
  1577. X        if(ison(headers[another_count]->status, NEW)) {
  1578. X          current = another_count+1;
  1579. X          break;    /* first one found give up */
  1580. X        }
  1581. X          }
  1582. X        }
  1583. X      }
  1584. X    }
  1585. X        get_page(current);
  1586. X    return(count);
  1587. X}
  1588. SHAR_EOF
  1589. chmod 0444 src/newmbox.c || echo "restore of src/newmbox.c fails"
  1590. echo "x - extracting src/opt_utils.c (Text)"
  1591. sed 's/^X//' << 'SHAR_EOF' > src/opt_utils.c &&
  1592. X
  1593. Xstatic char rcsid[] = "@(#)$Id: opt_utils.c,v 2.16 89/03/25 21:46:52 syd Exp $";
  1594. X
  1595. X/*******************************************************************************
  1596. X *  The Elm Mail System  -  $Revision: 2.16 $   $State: Exp $
  1597. X *
  1598. X *             Copyright (c) 1986, 1987 Dave Taylor
  1599. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1600. X *******************************************************************************
  1601. X * Bug reports, patches, comments, suggestions should be sent to:
  1602. X *
  1603. X *    Syd Weinstein, Elm Coordinator
  1604. X *    elm@dsinc.UUCP            dsinc!elm
  1605. X *
  1606. X *******************************************************************************
  1607. X * $Log:    opt_utils.c,v $
  1608. X * Revision 2.16  89/03/25  21:46:52  syd
  1609. X * Initial 2.2 Release checkin
  1610. X * 
  1611. X *
  1612. X ******************************************************************************/
  1613. X
  1614. X/** This file contains routines that might be needed for the various
  1615. X     machines that the mailer can run on.  Please check the Makefile
  1616. X     for more help and/or information. 
  1617. X
  1618. X**/
  1619. X
  1620. X#include "headers.h"
  1621. X#include <ctype.h>
  1622. X
  1623. X#ifdef BSD
  1624. X# include <pwd.h>
  1625. X#undef tolower
  1626. X#undef toupper
  1627. X#endif
  1628. X
  1629. X#ifndef GETHOSTNAME
  1630. X#  include <sys/types.h>
  1631. X#  include <sys/utsname.h>
  1632. X#endif
  1633. X
  1634. X#ifndef GETHOSTNAME
  1635. X
  1636. Xgethostname(hostname,size) /* get name of current host */
  1637. Xchar *hostname;
  1638. SHAR_EOF
  1639. echo "End of part 17"
  1640. echo "File src/opt_utils.c is continued in part 18"
  1641. echo "18" > s2_seq_.tmp
  1642. exit 0
  1643.  
  1644.